use crate::router::api::i_router::IRouter;
use axum::routing::get;
use axum::{Router, extract};
use std::ops::Add;

#[derive(Debug)]
pub struct AxumState {}

impl IRouter for AxumState {
    fn init_router(&self, router: Router) -> Router {
        // 在不同的handlers之间共享一些资源，以便达到更高效/更节约的技术目标
        let app_version = AppVersion {
            version: "1.0.0",
            code: 0,
        };

        // 如果在定义router的时候，使用了Nest或者Merge，有两条额外的规则：
        // a) 相同的router必须使用相同的State类型；
        // b) 如果router在不同的作用域中定义，则需要显式标注State类型
        // 因为在Router::with_state()调用前，所有的Router都会被推断为Router<()>
        // let gg = Router::new()
        //     .route("/hello", get(AxumState::hello))
        //     .with_state(app_version);

        let router1: Router = Router::new()
            .nest("/", AxumState::str_admin())
            .nest("/", AxumState::str_api())
            // .nest("/", AxumState::int_admin())
            // .nest("/", AxumState::int_api())
            .with_state(app_version);

        router.nest("/state", router1)
    }
}

impl AxumState {
    pub fn new() -> AxumState {
        AxumState {}
    }
    async fn hello(extract::State(app_version): extract::State<AppVersion>) -> &'static str {
        app_version.version
    }
    async fn code(extract::State(app_version): extract::State<AppVersion>) -> i32 {
        app_version.code.add(1)
    }
    fn str_admin() -> Router<AppVersion> {
        Router::new().route("/s/admin", get(AxumState::hello))
    }
    fn str_api() -> Router<AppVersion> {
        //顯示
        Router::new().route("/s/api", get(AxumState::hello))
    }
    // fn int_admin() -> Router<AppVersion> {
    //     Router::new()
    //         .route("/i/admin", get(AxumState::code))
    // }
    // fn int_api() -> Router<AppVersion> { //顯示
    //     Router::new()
    //         .route("/i/api", get(AxumState::code))
    // }
}

#[derive(Debug, Copy, Clone)]
struct AppVersion {
    version: &'static str,
    code: i32,
}
